// The printk function

#include "common.h"
#include "monitor.h"

static void printkint(int xx, int base, int sgn){
	static char digits[] = "0123456789ABCEDF";
	char buf[16];
	int i, neg;
	uint x;
	
	neg = 0;
	if(sgn && xx < 0){
		neg = 1;
		x = -xx;
	}else{
		x = xx;
	}
	
	i=0;
	do{
		buf[i++] = digits[x % base];
	}while((x /=base) != 0);
	if(neg)
		buf[i++] = '-';
	
	while(--i >=0)
		putc(buf[i]);
}

// Only understands %d, %x, %p, %s
void printk(char*fmt, ...){
	char *s;
	int c, i, state;
	uint *ap;
	
	state = 0;
	ap = (uint*)(void*)&fmt +1;
	for(i = 0; fmt[i]; i++){
		c = fmt[i] & 0xff;
		if(state == 0){
			if(c == '%'){
				state = '%';
			}else{
				putc(c);
			}
		}else if(state == '%'){
			if(c == 'd'){
				printkint(*ap, 10,1);
				ap++;
			}else if(c == 'x' || c == 'p'){
				printkint(*ap, 16, 0);
				ap++;
			}else if(c == 's'){
				s = (char*)*ap;
				ap++;
				if(s==0)
					s = "(null)";
				while(*s != 0){
					putc(*s);
					s++;
				}
			}else if(c == 'c'){
				putc(*ap);
				ap++;
			}else if(c == '%'){
				putc(c);
			}else{
				// Unknown Sequence. Print it to draw attention.
				putc('%');
				putc(c);
			}
			state = 0;
		}
	}
}
